package control 
{
	import base.constants.Events;
	import base.GObject;
	import appkit.responders.NResponder;
	
	public class StateMachine 
	{
		private var states:Vector.<String>;
		private var selected:Vector.<GObject>;
		
		/* check to see if the index passed to selected vector is valid */
		public function checkSelIndex(n:uint):Boolean
		{
			return n > -1 && n < selected.length;
		}
		
		/* deselect one gObject 
		 * this is not called from outside */
		private function noselect(n:uint):void
		{
			selected[n].unlock();
			selected[n].flip();
			selected.splice(n, 1);
		}
		
		/* deselect the last selected or a specific index */
		public function deselect(n:int = -1):void
		{
			if ( checkSelIndex(n))
				noselect( n);
			else if (selected.length > 0)
			{
				noselect( selected.length - 1);
			}
			NResponder.dispatch(Events.Free);
		}
		
		/* deselect all in selected vector 
		 * calling deselect with default arg should
		 * get rid of all of them */
		public function clearSelected():void
		{
			for (var i:uint = 0; i < selected.length; i++)
				deselect();
		}
		
		/* return last or specific index selected 
		 * checks if any exists */
		public function getSelected(n:int = -1):GObject
		{
			var g:GObject;
			if (checkSelIndex(n))
				g = selected[n];
			else if (selected.length > 0)
				g = selected.pop();
			
			return g;
		}
		
		/* pushes new selected */
		public function select(g:GObject):void
		{
			clearSelected();
			selected.push(g);
			changeState(Events.Selected);
		}
		
		/* pushes new state
		 * keeps state vector at max 3 history */
		public function changeState(s:String):void
		{
			if (states.length > 2)
				states.splice(0, 1);
			states.push(s);
		}
		
		/* returns last or specific state */
		public function getState(n:uint = -1):String
		{
			var s:String;
			if (n > -1 && n < states.length)
				s = states[n];
			else if (states.length > 0)
				s = states.pop();
			return s;
		}
		
		/* handle Events.Selected event */
		public function on_selected(g:GObject):void
		{
			select(g);
		}
		
		/* is selected empty? */
		public function hasSelected():Boolean
		{
			return selected.length > 0;
		}
		
		public function StateMachine() 
		{
			states = new Vector.<String>();
			NResponder.add(Events.Selected, on_selected);
		}
		
		
	}

}